package ${projectDomain}.filter;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBuffer;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import com.unswift.annotation.api.Api;
import com.unswift.annotation.api.ApiField;
import com.unswift.annotation.api.ApiMethod;
import ${projectDomain}.pojo.vo.ResponseBody;
import com.unswift.exception.CoreException;
import com.unswift.utils.ExceptionUtils;
import com.unswift.utils.ObjectUtils;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@Component
@Api(value="缓存body拦截器，此拦截器应当最先执行，允许其它拦截器读取缓存内容", author = "unswift", date = "2023-08-13", version = "1.0.0")
public class CloudGlobalFilter extends CloudFilter implements GlobalFilter, Ordered {

	@Value("${r'${unswift.server-route}'}")
	private String serverRoute;
	
	@Override
	@ApiMethod(value = "获取filter的执行顺序，值越小，越靠前，此值最好不要大于1，否则的话取到的path会没有路由", returns = @ApiField("执行顺序"))
	public int getOrder() {
		return Ordered.HIGHEST_PRECEDENCE;
	}

	@Override
	@ApiMethod(value = "拦截器执行方法，在此方法中拦截签名", params = {@ApiField( "http请求的封装，提供对HTTP的访问请求和响应"), @ApiField("委托" )})
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		try {
			String route = getRequestRoute(exchange.getRequest().getPath().value());
			HttpHeaders headers = exchange.getRequest().getHeaders();
			String language=headers.getFirst("Language");
			if(ObjectUtils.isNotEmpty(language)) {
				ExceptionUtils.setLanguage(language.toUpperCase());//设置异常使用的语言
			}
			if (exchange.getRequest().getHeaders().getContentType() == null) {
				if(ObjectUtils.isNotEmpty(route)) {
					ServerHttpRequest mutatedRequest=exchange.getRequest().mutate().header(serverRoute, route).build();
					return chain.filter(exchange.mutate().request(mutatedRequest).build());
				}
				return chain.filter(exchange);
			} else {
				DefaultDataBufferFactory defaultDataBufferFactory = new DefaultDataBufferFactory();
		        DefaultDataBuffer defaultDataBuffer = defaultDataBufferFactory.allocateBuffer(0);
		        Flux<DataBuffer> bodyDataBuffer = exchange.getRequest().getBody().defaultIfEmpty(defaultDataBuffer);
				return DataBufferUtils.join(bodyDataBuffer).flatMap(dataBuffer -> {
					DataBufferUtils.retain(dataBuffer);
					Flux<DataBuffer> cachedFlux = Flux
							.defer(() -> Flux.just(dataBuffer));
					ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) {
						@Override
						public Flux<DataBuffer> getBody() {
							return cachedFlux;
						}
					};
					return chain.filter(exchange.mutate().request(mutatedRequest).build());
				});
			}
		} catch (Exception e) {
			e.printStackTrace();
			CoreException exception = ExceptionUtils.message("gateway.handler.exception", e.getMessage());
			return this.toJson(exchange, ResponseBody.error(exception.getCode(), exception.getMessage()));
		}
	}

}
